package com.sherlocky.common;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.sf.json.JSONSerializer;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.math.NumberUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.sherlocky.exception.FileOperationException;
import com.sherlocky.exception.NoPermissionException;
import com.sherlocky.util.MD5Util;
import com.sherlocky.util.WebUtil;

import conf.Constants;

public abstract class BaseController {
	
	public static final int DEFAULT_PAGE_SIZE = 10;
	
	protected static Log logger = LogFactory.getLog(BaseController.class);
	
	/**
	 * 匿名访问控制，如果参数token不符合这个规则的话则不允许访问。
	 * <p>
	 *    token的生成规则：大写(Md5(日期+约定密钥)) 
	 * </p>
	 * @return true/false 是否有权限访问，如果传入参数device=mobile的话将不抛出异常，返回true/false
	 * @throws NoPermissionException 如果不允许访问的话
	 */
	public static boolean anonymousAccessControll(HttpServletRequest request, String... param) {
		//TODO
//		if(SecurityFacade.getUserId() != null) {
//			//已经登录了就不管了
//			return true;
//		}
		String random = request.getParameter("random");
		String timestamp = request.getParameter("timestamp");
		//判断加密后的参数是否有效
		String token = request.getParameter("token");
		StringBuffer rightTokenBeforeEncypt;
		//支持两种方式：一个是双方的时间保持一致，一个是通过传过来的参数来进行加密判断（这种可以有效解决双方时间不对应的问题）
		if(StringUtils.isNotBlank(random) && StringUtils.isNotBlank(timestamp)) {
			//规则：Md5(random + 参数+ timestamp + 约定密钥)
			rightTokenBeforeEncypt = new StringBuffer(random);
			if(param != null) {
				for (String s : param) {
					rightTokenBeforeEncypt.append(s);
				}
				rightTokenBeforeEncypt.append(timestamp + Constants.ANONYMOUSE_ACCESS_PRIVATE_KEY);
			}
		}else{
			//规则：Md5(参数+日期+约定密钥)
			rightTokenBeforeEncypt = new StringBuffer();
			if(param != null) {
				for (String s : param) {
					rightTokenBeforeEncypt.append(s);
				}
				rightTokenBeforeEncypt.append(new SimpleDateFormat("yyyy-MM-dd").format(new Date()) + Constants.ANONYMOUSE_ACCESS_PRIVATE_KEY);
			}
		}
		String rightToken = MD5Util.go2(rightTokenBeforeEncypt.toString()).toUpperCase();
		if(!StringUtils.equals(rightToken, token)) {
			//移动设备的话返回true/false
			logger.error("您没有权限访问资源：" + request.getRequestURI() + "，IP：" + WebUtil.getClientIP(request) + ",agent:" + request.getHeader("user-agent") 
					+ "\r\n正确的token：" + rightToken + ",传过来的token:" + token
					+ "\r\n加密前：" + rightTokenBeforeEncypt.toString());
			if(isMobileAccess(request)) {
				//移动设备的话返回true/false
				return false;
			}
			throw new NoPermissionException("您没有权限访问资源：" + request.getRequestURI() + "，IP：" + WebUtil.getClientIP(request) + ",agent:" + request.getHeader("user-agent"));
		}
		return true;
	}
	
	public static boolean isMobileAccess(HttpServletRequest request) {
		return "mobile".equals(request.getParameter("device"));
	}
	
	public final String redirect(HttpServletRequest request, HttpServletResponse response, String path) {
		if(!StringUtils.startsWith(path, "http") && !StringUtils.startsWith(path, "/")) {
			path = "/" + path;
		}
		try {
			if(StringUtils.startsWith(path, "http")) {
				response.sendRedirect(path);
			}else{
				response.sendRedirect(request.getContextPath() + path);
			}
			return null;
		} catch (IOException e) {
			e.printStackTrace();
		}
		return "redirect: " + path;
	}
	
	protected int getInt(HttpServletRequest request, String param, int defaultValue) {
		String value = request.getParameter(param);
		return NumberUtils.isNumber(value) ? Integer.parseInt(value) : defaultValue;
	}
	
	protected Integer getInteger(HttpServletRequest request, String param) {
		String value = request.getParameter(param);
		return NumberUtils.isNumber(value) ? Integer.parseInt(value) : null;
	}
	
	protected Long getLong(HttpServletRequest request, String param) {
		String value = request.getParameter(param);
		return NumberUtils.isNumber(value) ? Long.parseLong(value) : null;
	}
	
	protected Long getLong(HttpServletRequest request, String param, Integer defaultValue) {
		String value = request.getParameter(param);
		return NumberUtils.isNumber(value) ? Long.parseLong(value) : defaultValue.longValue();
	}
	
	protected String get(HttpServletRequest request, String param) {
		String value = request.getParameter(param);
		return value != null ? value.trim() : null;
	}
	
	protected String get(HttpServletRequest request, String param, String defaultValue) {
		String value = request.getParameter(param);
		return StringUtils.isNotBlank(value)? value.trim() : defaultValue;
	}
	
	protected String[] getValues(HttpServletRequest request, String param) {
		String[] values = request.getParameterValues(param);
		return values == null ? new String[0] : values;
	}
	
	protected void sendMessage(HttpServletResponse response, String str) throws Exception{
		response.setContentType("text/html; charset=utf-8");
		PrintWriter writer = response.getWriter();
		writer.print(str);
		writer.close();
		response.flushBuffer();
	}
	
	protected void sendMessage(HttpServletResponse response, String str, String contentType) throws Exception{
		response.setContentType(contentType + "; charset=utf-8");
		PrintWriter writer = response.getWriter();
		writer.print(str);
		writer.close();
		response.flushBuffer();
	}
	
	/**
	 * 将某个对象转换成json格式并发送到客户端
	 * @param response
	 * @param obj
	 * @throws Exception
	 */
	protected void sendJsonMessage(HttpServletResponse response, Object obj) throws Exception{
		response.setContentType("text/html; charset=utf-8");
		PrintWriter writer = response.getWriter();
		writer.print(toJsonString(obj));
		writer.close();
		response.flushBuffer();
	}
	
	protected void sendJsonMessageIgnoreEmptyProperty(HttpServletResponse response, Object obj) throws Exception{
		response.setContentType("text/html; charset=utf-8");
		PrintWriter writer = response.getWriter();
		com.alibaba.fastjson.serializer.JSONSerializer.write(writer, obj);
		writer.close();
		response.flushBuffer();
	}
	
	protected void sendXmlMessage(HttpServletResponse response, Map<String,String> map) throws Exception{
		PrintWriter pw = response.getWriter();
		response.setContentType("text/xml");
		response.setCharacterEncoding("UTF-8");
		pw.write("<?xml version='1.0' encoding='UTF-8'?>");
		
		Iterator<String> it =  map.keySet().iterator();
		pw.write("<result>");
		while(it.hasNext()){
			String key = it.next();
			String val = map.get(key);
			pw.write("<"+key+">"+val+"</"+key+">");
		}
		pw.write("</result>");
		pw.close();
		response.flushBuffer();
	}
	
	/**
	 * 是否是jqGrid自带的快速查询
	 * @param request
	 * @return
	 */
	protected boolean isQuickQuery(HttpServletRequest request) {
		return "true".equals(request.getParameter("_search"));
	}
	
	protected void set(HttpServletRequest request, String paramName, Object value) {
		request.setAttribute(paramName, value);
	}
	
	protected void setNotEmpty(HttpServletRequest request, String paramName, List value) {
		if(value != null && value.size() > 0) {
			request.setAttribute(paramName, value);
		}
	}

	
	protected String toJsonString(Object o) {
		return JSONSerializer.toJSON(o).toString();
	}
	
	/**
	 * 文件流输出
	 * @param response
	 * @param file
	 * @param contentType
	 * @param buf 默认1024
	 * @throws Exception
	 */
	protected void outputStream(HttpServletResponse response, File file, String contentType, Integer buf) throws Exception {
		if( null != file && file.canRead() && file.isFile() ) {
			this.outputStream(response, new FileInputStream(file), contentType, buf);
		} else {
			throw new FileOperationException("文件不存在或不是文件");
		}
	}
	
	/**
	 * 文件流输出
	 * @param response
	 * @param is
	 * @param contentType
	 * @param buf 默认1024
	 * @throws IOException
	 */
	protected void outputStream(HttpServletResponse response, InputStream is, String contentType, Integer buf) throws IOException {
		if( null == buf || buf == 0) {
			buf = 1024;
		}
		if( StringUtils.isNotBlank(contentType) ) {
			response.setContentType(contentType);
		} else {
			response.setContentType("image/jpg");
		}
		
		if (is != null) {
			try {
				byte[] b = new byte[buf];
				OutputStream os = response.getOutputStream();
				int len = 0;
				while((len = is.read(b)) != -1 ) {
					os.write(b, 0, len);
				}
				os.close();
			} catch (Exception e) {
				throw new FileOperationException("文件读取错误");
			} finally {
				if( null != is ) {
					is.close();
				}
			}
		} else {
			throw new IOException("数据流传输错误，数据流为null");
		}
	}
}
